package v2

import (
	rpcv1 "gluenet/internal/agent/api/rpc/v1"
	metav1 "gluenet/pkg/agent/option"
	corev1 "gluenet/pkg/agent/types"
	"gluenet/pkg/agent/v2/rpc"
)

type HelmGetter interface {
	ReleaseGetter
	ChartsGetter
}

type ReleaseGetter interface {
	Releases(guid string) ReleaseInterface
}

type ReleaseInterface interface {
	// ask agent to install a helm chart
	//
	// Example:
	// 	release := corev1.Release{
	// 		ReleaseName: `test-release`,
	// 		ChartName:   `/home/fhl/workplace/go/gluenet/deploy/collectors/jaeger`,
	// 	}
	//
	//	 rlt, err := cli.Releases(UserHelmApp).Create(
	// 		&release,
	// 		metav1.CreateOptions{
	// 			WithJaeger:  false,
	// 			WithLinkerd: false},
	// 	)
	Create(release *corev1.Release, opt metav1.CreateOptions) (*corev1.HelmReleaseDetailObj, error)

	// ask agent to uninstall a helm chart
	//
	// Example:
	// 	err := cli.Releases(UserHelmApp).Delete(metav1.DeleteOptions{})
	Delete(opt metav1.DeleteOptions) error

	// ask agent to get a helm release's detial info
	//
	// Example:
	// 	rlt, err := cli.Releases(UserHelmApp).Get(metav1.GetOptions{})
	Get(opt metav1.GetOptions) (*corev1.HelmReleaseDetailObj, error)
}

type releases struct {
	client rpc.Interface
	guid   string
}

func newReleases(c *CoreClient, guid string) *releases {
	return &releases{
		client: c.RPCClient(),
		guid:   guid,
	}
}

func (c *releases) Create(release *corev1.Release, opt metav1.CreateOptions) (result *corev1.HelmReleaseDetailObj, err error) {
	result = &corev1.HelmReleaseDetailObj{}
	err = c.client.Invoke().
		Api(rpcv1.CreateHelmRelease).
		Guid(c.guid).
		Resource(rpcv1.HELM_RELEASE_RESOURCE).
		Options(opt).
		Spec(*release).
		Do().
		Into(result)
	return
}

func (c *releases) Delete(opt metav1.DeleteOptions) error {
	return c.client.Invoke().
		Api(rpcv1.DeleteHelmRelease).
		Guid(c.guid).
		Resource(rpcv1.HELM_RELEASE_RESOURCE).
		Do().
		Error()
}

func (c *releases) Get(opt metav1.GetOptions) (result *corev1.HelmReleaseDetailObj, err error) {
	result = &corev1.HelmReleaseDetailObj{}
	err = c.client.Invoke().
		Api(rpcv1.GetHelmRelease).
		Guid(c.guid).
		Resource(rpcv1.HELM_RELEASE_RESOURCE).
		Do().
		Into(result)
	return
}

type ChartsGetter interface {
	Charts(guid string) ChartInterface
}

type ChartInterface interface {
	List() ([]*corev1.ChartDetial, error)
}

type charts struct {
	client rpc.Interface
	guid   string
}

func newCharts(c *CoreClient, guid string) *charts {
	return &charts{
		client: c.RPCClient(),
		guid:   guid,
	}
}

func (c *charts) List() ([]*corev1.ChartDetial, error) {
	panic("implement")
}
